﻿using Microsoft.AspNetCore.SignalR;
using Microsoft.VisualBasic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Serialization;
using VOL.Entity.DomainModels;
using static System.Net.Mime.MediaTypeNames;

namespace VOL.Entity.VM
{
    #region PLC
    /// <summary>
    /// 
    /// </summary>
    public class PLCData
    {
        public string EquipmentId { get; set; }
        public string EquipmentCode { get; set; }
        public string EquipmentName { get; set; }
        public double X { get; set; }
        public double Y { get; set; }
    }
    #endregion
    /// <summary>
    /// 工单状态
    /// </summary>
    public enum StatusOrder
    {
        //0新建 /激活/保留/废除 1冻结 -2生产-3暂停 -4紧急暂停     5-终止' 
        /// <summary>
        /// 0新建
        /// </summary>
        New = 0,
        /// <summary>
        /// 1冻结
        /// </summary>
        Freeze = 1,
        /// <summary>
        /// 2生产
        /// </summary>
        Produce = 2,
        /// <summary>
        /// 暂停
        /// </summary>
        Pause = 3,

        /// <summary>
        /// -4紧急暂停 
        /// </summary>
        EmergencyPause = 4,
        /// <summary>
        ///  5-终止' 
        /// </summary>
        Stop = 5,
        Completed = 6,
    }
    /// <summary>
    /// 生产状态
    /// </summary>
    public enum StatusProcess
    {
        /// <summary>
        /// 0未开始
        /// </summary>
        NotStart = 0,
        /// <summary>
        /// 1冻结
        /// </summary>
        Freeze = 1,
        /// <summary>
        /// 2生产
        /// </summary>
        Produce = 2,
        /// <summary>
        /// 暂停
        /// </summary>
        Pause = 3,

        /// <summary>
        /// -4紧急暂停 
        /// </summary>
        EmergencyPause = 4,
        /// <summary>
        ///  5-终止' 
        /// </summary>
        Stop = 5,
        Completed = 6,
    }
    public enum StatusAction
    {
        /// <summary>
        /// 未执行
        /// </summary>
        NotExecuted = 1,
        /// <summary>
        /// 执行中
        /// </summary>
        Executing = 2,
        /// <summary>
        /// 已完成
        /// </summary>
        Completed = 3,
        /// <summary>
        /// 异常
        /// </summary>
        Exception = 4,

        /// <summary>
        /// 重做
        /// </summary>
        Redo = 5
    }
    /// <summary>
    /// 设备状态
    /// </summary>
    public enum StatusEqu
    {
        /// <summary>
        /// 自动运行
        /// </summary>
        Automatic = 0,
        /// <summary>
        /// 待机
        /// </summary>
        Standby = 1,
        /// <summary>
        /// 正常停机
        /// </summary>
        NormalShutdown = 2,
        /// <summary>
        /// 故障停机
        /// </summary>
        FaultShutdown = 3,
        /// <summary>
        /// 待料
        /// </summary>
        WaitingMaterials = 4,


        FullMaterial = 5
    }
    public enum MQqueue
    {
        /// <summary>
        /// MQ队列 Key
        /// </summary>
        Equ_SendTask,

        /// <summary>
        /// MQ队列 Key 
        /// </summary>
        Equ_ReceiveTask,
        /// <summary>
        /// MQ队列 Key
        /// </summary>
        Equ_SendToolCheck,
        /// <summary>
        /// CNC 1
        /// </summary>
        Equ_SendTask_1,
        /// <summary>
        /// CNC 2
        /// </summary>
        Equ_SendTask_2,
        Equ_SendTask_3,
        Equ_SendTask_4,
        Equ_SendTask_5,
        Equ_SendTask_6,
        Equ_SendTask_7,
        Equ_SendTask_8,
        Equ_SendTask_9,
        Equ_SendTask_10,
        Equ_SendTask_11,
        Equ_SendTask_12,
        Equ_SendTask_13,
        Equ_SendTask_14,
        Equ_SendTask_15,
        Equ_SendTask_16,
        Equ_SendTask_17,
        Equ_SendTask_18,
        Equ_SendTask_19,
        Equ_SendTask_20,
        Equ_SendTask_21,
        Equ_SendTask_22,
        Equ_SendTask_23,
        Equ_SendTask_24,
        Equ_SendTask_25,
        Equ_SendTask_26,
        Equ_SendTask_27,
        Equ_SendTask_28,
        Equ_SendTask_29,
        Equ_SendTask_30,
        Equ_SendTask_31,
        Equ_SendTask_32,
        Equ_SendTask_33,
        Equ_SendTask_34,
        Equ_SendTask_35,
        Equ_SendTask_36,
        Equ_SendTask_37,
        Equ_SendTask_38,
        Equ_SendTask_39,
        Equ_SendTask_40,
        Equ_SendTask_41,
        Equ_SendTask_42,
        Equ_SendTask_43,
        Equ_SendTask_44,
        Equ_SendTask_45,
        Equ_SendTask_46,
        Equ_SendTask_47,
        Equ_SendTask_48,
        Equ_SendTask_49,
        Equ_SendTask_50

    }
    public class UserDto : BaseDto
    {
        private string userName;

        public string UserName
        {
            get { return userName; }
            set { userName = value; OnPropertyChanged(); }
        }

        private string account;

        public string Account
        {
            get { return account; }
            set { account = value; OnPropertyChanged(); }
        }

        private string passWord;

        public string PassWord
        {
            get { return passWord; }
            set { passWord = value; OnPropertyChanged(); }
        }
    }
    public class Equ_TaskAuto
    {
        public string OrderCode { get; set; }
        //public int? ActionSort { get; set; }
    }
    public class Equ_TaskAutoN
    {
        public string EquipmentId { get; set; }
        public decimal CurrentX { get; set; } = 0;
        public decimal CurrentY { get; set; } = 0;
        public string TaskNo { get; set; }
        public string Status { get; set; }
    }
    public class Equ_TaskReceive
    {
        public string Id { get; set; }
        public string TaskNo { get; set; }
        public string Status { get; set; }
        public string DisuseState { get; set; }
        public string FaultContent { get; set; }
        public string FaultType { get; set; }
    }
    public static class ApplicationStatus
    {
        // 使用 volatile 确保多线程可见性
        private static volatile bool _isRunning = false;

        // 线程安全访问锁
        private static readonly object _syncLock = new object();

        /// <summary>
        /// 获取当前运行状态（线程安全）
        /// </summary>
        public static bool IsRunning
        {
            get
            {
                lock (_syncLock)
                {
                    return _isRunning;
                }
            }
        }

        /// <summary>
        /// 安全修改运行状态
        /// </summary>
        public static void SetRunningState(bool newState)
        {
            lock (_syncLock)
            {
                _isRunning = newState;
            }
        }
    }
    public static class AtomicStatus
    {
        // 使用内存屏障保证原子操作
        private static int _isRunningFlag = 0; // 0=停止，1=运行

        public static bool IsRunning =>
            Interlocked.CompareExchange(ref _isRunningFlag, 1, 1) == 1;

        public static bool Start()
        {
            return Interlocked.CompareExchange(ref _isRunningFlag, 1, 0) == 0;
        }

        public static bool Stop()
        {
            return Interlocked.CompareExchange(ref _isRunningFlag, 0, 1) == 1;
        }
    }
    public class SingleTaskQueue : IDisposable
    {
        // 任务存储队列（线程安全）
        private readonly ConcurrentQueue<Action> _taskQueue = new ConcurrentQueue<Action>();

        // 执行状态锁
        private readonly object _syncLock = new object();

        // 是否正在执行任务的标记
        private bool _isProcessing;

        /// <summary>
        /// 添加任务到队列
        /// </summary>
        public void Enqueue(Action task)
        {
            _taskQueue.Enqueue(task);
            TryProcessNext();
        }

        /// <summary>
        /// 尝试触发下一个任务执行
        /// </summary>
        private void TryProcessNext()
        {
            lock (_syncLock)
            {
                // 如果已有任务在执行或队列为空，则返回
                if (_isProcessing || _taskQueue.IsEmpty) return;

                _isProcessing = true;
            }

            // 异步执行防止阻塞
            Task.Run(() => ProcessTask());
        }

        /// <summary>
        /// 实际任务处理逻辑
        /// </summary>
        private void ProcessTask()
        {
            try
            {
                while (true)
                {
                    if (!_taskQueue.TryDequeue(out var task)) break;

                    // 执行实际任务
                    task.Invoke();
                }
            }
            finally
            {
                lock (_syncLock)
                {
                    _isProcessing = false;
                }

                // 检查是否有待处理任务
                TryProcessNext();
            }
        }

        public void Dispose()
        {
            _taskQueue.Clear();
        }
    }
    public class MsgInfo
    {
        public string Title { get; set; }
        public string MsgContent { get; set; }
    }
    // SignalR Hub
    public class ChatHub : Microsoft.AspNetCore.SignalR.Hub
    {
        public async Task SendMessage(string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", message);
        }

        public override async Task OnConnectedAsync()
        {
            await Clients.All.SendAsync("ReceiveMessage", $"用户 {Context.ConnectionId} 已连接");
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception? exception)
        {
            await Clients.All.SendAsync("ReceiveMessage", $"用户 {Context.ConnectionId} 已断开连接");
            await base.OnDisconnectedAsync(exception);
        }

        /// <summary>
        /// 这个方法允许客户端调用
        /// </summary>
        public Task UpdateDataServer(DataStatus data)
        {
            // 在里面可以调用客户端的方法
            return Clients.All.SendAsync("UpdateData", data);
        }
    }

    public class DataStatus
    {
        public string Status1 { get; set; }
        public string Status2 { get; set; }
    }
    public class PlcPlan
    {
        public string togetherSeq {  get; set; }
        public string isInOut { get; set; } //
        public string vendor_code { get; set; }
        public string Description { get; set; }
        public string IsWriteRfid { get; set; } 
        //使能
        public string IsUse { get; set; } 
        public string HolderTypeId { get; set; }
        public string RfidCode { get; set; }
        public string handle_type { get; set; }
        public string FaultNoMeasure { get; set; }

        public string FaultNo { get; set; }
        public string IsFalut { get; set; }
        public string Identifier { get; set; }
        public decimal? R { get; set; }
        public decimal? reality_knife_length { get; set; }
        public decimal? reality_pairing_length { get; set; }
        public decimal? knife_width { get; set; }
        public decimal? reality_knife_width { get; set; }
        public decimal? knife_length { get; set; }
        public decimal? Ace1LTheory { get; set; }
        public decimal? Ace1L { get; set; }
        public decimal? HolderBD { get; set; }
        public decimal? HolderBDTheory { get; set; }


        public decimal? HolderLTheory { get; set; }
        public string tool_name { get; set; }
        public string Holder_Code { get; set; }
        public decimal? HolderL { get; set; }
        public int? location { get; set; }
        /// <summary>
        /// 放刀完成
        /// </summary>
        public string IsKnifeCompleted { get; set; }
        /// <summary>
        /// 放刀中
        /// </summary>
        public string IsKnifeOngoing { get; set; }
        /// <summary>
        /// 放刀位置编号
        /// </summary>
        public string KnifeLocationNumber { get; set; }
        public List<Sys_DictionaryList> sys_DictionaryLists { get; set; }
        public string measureStartTime { get; set; }
        public string measureEndTime { get; set; }

    }
    public class PlcWorkpieceRFID
    {
        public string Order_Id { get; set; }
        public string Id { get; set; }

    }
    public class PlcToolRFID
    {
        public string Identifier { get; set; }
        public int program_seq { get; set; }
    }
    public class PlcReceive
    {

    }
   
    public class LargeData
    {
        //public string orderCode { get; set; }
        //public string value { get; set; }
        //public string valueOne { get; set; }
        //public string valueTwo { get; set; }
        //public string cncNum { get; set; }
        //public string programe { get; set; }
        //public float ToolSpeed { get; set; }
        //public float ToolLoad { get; set; }
        //public string cncNo{ get; set; }
        //public string toolName { get; set; }

        public DateTime Ts { get; set; }
        public string BatCode { get; set; }
        public string OrderCode { get; set; }
        public string ProgramName { get; set; }
        public string CNCNo { get; set; }
        public string ToolName { get; set; }
        public float ToolSpeed { get; set; }
        public float ToolLoad { get; set; }
        //public List<LargeDataml> largeDatas { get; set; }
    }
    public class LargeDataml
    {
        public string orderCode { get; set; }
        public string value { get; set; }
        public string valueOne { get; set; }
        public string valueTwo { get; set; }
        public string cncNum { get; set; }
        public string programe { get; set; }
    }

    public class PlcAlignRecordTask
    {

        public string TaskNo { get; set; }
        public float AY { get; set; }
        public float BY { get; set; }
        public float ABInstance { get; set; }
        public float ARealityY { get; set; }
        public float BRealityY { get; set; }
        public float StepLocation { get; set; }
        public float FirstStopLocation { get; set; }
        public float AllinValue { get; set; }
        public float TwoDistance { get; set; }
        public float NeedValue { get; set; }
        public float NeedDistance { get; set; }
        public float BitVariable00 { get; set; }
        public float CNC_NUM { get; set; }
    }
    public class Plcequ
    {

        public string CNC_NUM { get; set; }
        public bool OpenedDoor1 { get; set; }
        public bool ClosedDoor1 { get; set; }
        public bool OpenedDoor2 { get; set; }
        public bool ClosedDoor2 { get; set; }
        public bool OpenedDuiDaoDoor { get; set; }
        public bool ClosedDuiDaoDoor { get; set; }
        public bool OpenedDangliao { get; set; }
        public bool ClosedDangliao { get; set; }
        public bool OpenedCi { get; set; }
        public bool ClosedCi { get; set; }
        public bool WarningCi { get; set; }
        public bool JiaDao { get; set; }
        public bool SongDao { get; set; }
        public bool M30 { get; set; }
        public bool AllowShangXiaHuan { get; set; }
        public bool AllowHuanDao { get; set; }
        public string RunStatus { get; set; }
        public string Time { get; set; }
    }
    public class Select
    {// [ { key: "1", value: "text1"},{ key: "2", value: "text2"}];
        public string key { get; set; }
        public string value { get; set; }
        public string sort { get; set; }
    }

    /// &lt;summary&gt;
    /// 获取plc 给1号机床的命令状态值
    /// &lt;/summary&gt;
    public record MachineState
    {
        public short CNC_NUM { get; set; }
        public float AY { get; set; }
        public float BY { get; set; }
        public float ABInstance { get; set; }
        public float ARealityY { get; set; }
        public float BRealityY { get; set; }
        public float StepLocation { get; set; }
        public float FirstStopLocation { get; set; }
        public float AllinValue { get; set; }
        public float TwoDistance { get; set; }
        public float NeedValue { get; set; }
        public float NeedDistance { get; set; }
        /// &lt;summary&gt;
        /// DB1.DBX0.0
        /// &lt;/summary&gt;
        public bool BitVariable00 { get; set; }


    }
    public class Taskgenerate
    {
        public string OrderCode { get; set; }
    }
    public class Equ_OrderReceive
    {
        public string OrderCode { get; set; }
        public string Status { get; set; }
    }
    public class Equ_TaskSend
    {
        public string TaskNo { get; set; }
    }
    public class Equ_TaskSendReady
    {
        public int OrderCode { get; set; }
        public decimal Width { get; set; }
    }
    public class Equ_TASKVM
    {
        /// <summary>
        /// 任务状态 1:未执行 2:执行中 3:已完成 4:异常
        /// </summary>
        public string Status { get; set; }
        /// <summary>
        /// 任务号
        /// </summary>
        public string TaskNo { get; set; }
        /// <summary>
        /// 设备号
        /// </summary>
        public string EquipmentCode { get; set; }
        /// <summary>
        /// 指令
        /// </summary>
        public string Command { get; set; }
        /// <summary>
        /// 生产工单号
        /// </summary>
        public string WorkOrderCode { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string OrderCode { get; set; }
        /// <summary>
        /// 物料点位
        /// </summary>
        public int SubPathNo { get; set; }
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime? StartTime { get; set; }
        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime? EndTime { get; set; }
        public int Unit { get; set; }
        /// <summary>
        /// DbCode
        /// </summary>
        public string DbCode { get; set; }
        /// <summary>
        /// 程序名称
        /// </summary>
        public string ProgramName { get; set; }
        /// <summary>
        /// 刀具Id
        /// </summary>
        public string toolId { get; set; }
        /// <summary>
        /// 1：上刀（第一把刀） 2：换刀  3：卸刀（最后一把刀）
        /// </summary>
        public string ToolCommandId { get; set; }


        public CurrentTool CurrentTool { get; set; }
        public CncInfo CncInfo { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string FaultContent { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string FaultType { get; set; }



    }
    public class CncInfo
    {
        public UpperWorkOrder WorkOrder { get; set; }
        public UpperMachine Machine { get; set; }

    }
    public class UpperMachine
    {
        /// <summary>
        /// 主键
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 机床名称
        /// </summary>
        public string? Name { get; set; }

        /// <summary>
        /// 机床规格
        /// </summary>
        public string? LatheSpec { get; set; }

        /// <summary>
        /// 机床系统
        /// </summary>
        public string MachineType { get; set; } = null!;

        /// <summary>
        /// 加工类型
        /// </summary>
        public string? ProcessType { get; set; }

        /// <summary>
        /// 刀补平台补充值
        /// </summary>
        public double G54Supplement { get; set; }

        /// <summary>
        /// 夹爪平台高度
        /// </summary>
        public double ToolHeight { get; set; }

        /// <summary>
        /// 加工精度
        /// </summary>
        public string? ProcessPrecision { get; set; }

        /// <summary>
        /// 行程X
        /// </summary>
        public double? ItineraryX { get; set; }

        /// <summary>
        /// 行程Y
        /// </summary>
        public double? ItineraryY { get; set; }

        /// <summary>
        /// 行程Z
        /// </summary>
        public double? ItineraryZ { get; set; }

        /// <summary>
        /// 基准点X
        /// </summary>
        public double BasicX { get; set; }

        /// <summary>
        /// 基准点Y
        /// </summary>
        public double BasicY { get; set; }

        /// <summary>
        /// 基准点Z
        /// </summary>
        public double BasicZ { get; set; }

        /// <summary>
        /// 换刀位置x
        /// </summary>
        public double? ChangeToolX { get; set; }

        /// <summary>
        /// 换刀位置Y
        /// </summary>
        public double? ChangeToolY { get; set; }

        /// <summary>
        /// 换刀位置z
        /// </summary>
        public double? ChangeToolZ { get; set; }

        /// <summary>
        /// 上料位置x
        /// </summary>
        public double? FeedX { get; set; }

        /// <summary>
        /// 上料位置y
        /// </summary>
        public double? FeedY { get; set; }

        /// <summary>
        /// 上料位置z
        /// </summary>
        public double? FeedZ { get; set; }

        /// <summary>
        /// 号机表示
        /// </summary>
        public int? Unit { get; set; }

        /// <summary>
        /// 主机地址
        /// </summary>
        public string? Host { get; set; }

        /// <summary>
        /// 端口号
        /// </summary>
        public int? Port { get; set; }

        /// <summary>
        /// NC类型
        /// </summary>
        public string? NcType { get; set; }

        /// <summary>
        /// NC卡编号
        /// </summary>
        public string? NcCardNo { get; set; }

        /// <summary>
        /// 使用状态
        /// </summary>
        public bool UseStatus { get; set; }

        //public virtual ICollection<UpperMachineWorkorder> UpperMachineWorkorders { get; } = new List<UpperMachineWorkorder>();
    }
    /// <summary>
    /// 工单表
    /// </summary>
    public partial class UpperWorkOrder
    {
        /// <summary>
        /// 主键
        /// </summary>
        //[JsonProperty("work_order_id")]
        public int WorkOrderId { get; set; }

        /// <summary>
        /// 工单编号
        /// </summary>
        //[JsonProperty("work_order_number")]
        public string? WorkOrderNumber { get; set; }

        /// <summary>
        /// 工件id(外键)
        /// </summary>
        //[JsonProperty("workpiece_id")]
        public int? WorkpieceId { get; set; }

        /// <summary>
        /// 优先等级：1，2，3，4
        /// </summary>
        //[JsonProperty("priority")]
        public int? Priority { get; set; }

        /// <summary>
        /// 材料表id
        /// </summary>
        //[JsonProperty("material_id")]
        public int? MaterialId { get; set; }

        /// <summary>
        /// 粗加工：1，半精加工：3，精加工：5
        /// </summary>
        //[JsonProperty("processing_grade")]
        public int ProcessingGrade { get; set; }

        /// <summary>
        /// 长度
        /// </summary>
        public double? Length { get; set; }

        /// <summary>
        /// 宽度
        /// </summary>
        public double? Width { get; set; }

        /// <summary>
        /// 高度
        /// </summary>
        public double? Height { get; set; }

        /// <summary>
        /// 打表程序名-DB
        /// </summary>
        public string? MeasureNumber { get; set; }

        /// <summary>
        /// 分中程序名-FZ
        /// </summary>
        public string? CentringNumber { get; set; }

        /// <summary>
        /// 放平程序名-FP
        /// </summary>
        public string? MakeLevelNumber { get; set; }

        /// <summary>
        /// 精度
        /// </summary>
        public double? Accuracy { get; set; }

        /// <summary>
        /// 0:未开始，1：加工中，2：已完成
        /// </summary>
        public uint ProcessStatus { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime? CreatTime { get; set; }

        /// <summary>
        /// 修改时间
        /// </summary>
        public DateTime? UpdateTime { get; set; }

        /// <summary>
        /// 是否删除：0：否，1：是
        /// </summary>
        public ulong? IsDeleted { get; set; }

        //public virtual ICollection<UpperFtpmachiningcenter> UpperFtpmachiningcenters { get; } = new List<UpperFtpmachiningcenter>();

        //public virtual ICollection<UpperMachineWorkorder> UpperMachineWorkorders { get; } = new List<UpperMachineWorkorder>();

        public virtual UpperWorkpiece? Workpiece { get; set; }
    }
    /// <summary>
    /// 工件表
    /// </summary>
    public partial class UpperWorkpiece
    {
        //public int Id { get; set; }

        ///// <summary>
        ///// 模具名称
        ///// </summary>
        //public string? WorkpieceName { get; set; }

        ///// <summary>
        ///// 工件型号
        ///// </summary>
        //public string? WorkpieceType { get; set; }

        ///// <summary>
        ///// 材质
        ///// </summary>
        //public string? Material { get; set; }

        ///// <summary>
        ///// 目标精度
        ///// </summary>
        //public double? TargetAccuracy { get; set; }

        ///// <summary>
        ///// 加工机床
        ///// </summary>
        //public int Machine { get; set; }

        ///// <summary>
        ///// 工件长度
        ///// </summary>
        //public double? WorkpieceLength { get; set; }

        ///// <summary>
        ///// 工件宽度
        ///// </summary>
        //public double? WorkpieceWidth { get; set; }

        ///// <summary>
        ///// 工件高度
        ///// </summary>
        //public double? WorkpieceHeight { get; set; }

        ///// <summary>
        ///// 预设中心点x距离
        ///// </summary>
        //public double XInstance { get; set; }

        ///// <summary>
        ///// 预设中心点y距离
        ///// </summary>
        //public double YInstance { get; set; }

        ///// <summary>
        ///// 预设中心点z距离
        ///// </summary>
        //public double ZInstance { get; set; }

        //public DateTime? CreateTime { get; set; }

        //public DateTime? UpdateTime { get; set; }

        //public ulong? IsDelete { get; set; }




        /// <summary>
        /// 工件宽度
        /// </summary>
        public double? WorkpieceWidth { get; set; }


        /// <summary>
        /// 预设中心点x距离
        /// </summary>
        public double XInstance { get; set; }

        /// <summary>
        /// 预设中心点y距离
        /// </summary>
        public double YInstance { get; set; }

        /// <summary>
        /// 预设中心点z距离
        /// </summary>
        public double ZInstance { get; set; }

        //public virtual ICollection<UpperWorkOrder> UpperWorkOrders { get; } = new List<UpperWorkOrder>();
    }
    public class upper_work_orderVM : upper_work_order
    {
        //public virtual ICollection<upper_ftpmachiningcenter > UpperFtpmachiningcenters { get; } = new List<UpperFtpmachiningcenter>();

        //public virtual ICollection<upper_machine UpperMachineWorkorder> UpperMachineWorkorders { get; } = new List<UpperMachineWorkorder>();

        public upper_workpiece Workpiece { get; set; }
    }
    public class CurrentTool
    {
        public decimal RealityR { get; set; }
        public decimal RealityKnifeWidth { get; set; }
        public decimal RealityPairingLength { get; set; }
        public decimal Accuracy { get; set; }
        public int Location { get; set; }
        /// <summary>
        /// 刀补长度
        /// </summary>
        public decimal ZIndex { get; set; }
    }
    /// <summary>
    /// 1.对刀长度=刀具长度+刀柄长 +加长杆长  
    //  总长必须[0, 3] 
    //2.刀头直径[0, 0.02] 正常[0.02, 0.05] 刀摆[0.05, +] 报警（装错刀）
    //3.R角 4.C角
    //5.刀柄长[-3, 0.5]      6.刀柄半径[-0.5, 0.5]
    //4.加长杆长[-3, 0.5]        5.加长杆直径[-1, 1]
    //4.加长杆长(2) 5.加长杆直径(2)
    //4.加长杆长(3) 5.加长杆直径(3)
    //var v1 = (double)PlcHelper.Instance.ReadReal(6, 0);//R角度
    //var v2 = (double)PlcHelper.Instance.ReadReal(6, 4);//直径
    //var v3 = (double)PlcHelper.Instance.ReadReal(6, 8);//刀长到中心线误差
    //var v4 = (double)PlcHelper.Instance.ReadReal(6, 12);//刀柄直径到中心线误差
    //var v5 = (double)PlcHelper.Instance.ReadReal(6, 12);//刀柄半径
    /// </summary>
    public class CurrentToolPLC
    {
        public string Msg { get; set; }
        /// <summary>
        /// reality_R
        /// var v1 = (double)PlcHelper.Instance.ReadReal(6, 0);//R角度
        /// </summary>
        public decimal RealityR { get; set; }
        public bool IsRealityR { get; set; }
        public decimal RealityKnifeWidth { get; set; }
        /// <summary>
        /// var v2 = (double)PlcHelper.Instance.ReadReal(6, 4);//直径
        /// </summary>
        public decimal HolderBD { get; set; }

        public bool IsHolderBD { get; set; }
        /// <summary>
        /// 实际对刀长度
        /// //var v3 = (double)PlcHelper.Instance.ReadReal(6, 8);//刀长到中心线误差
        /// </summary>
        public decimal RealityPairingLength { get; set; }
        public bool IsRealityPairingLength { get; set; }
        public decimal Accuracy { get; set; }
        /// <summary>
        /// var v4 = (double)PlcHelper.Instance.ReadReal(6, 12);//刀柄直径到中心线误差
        /// </summary>
        public decimal knife_length { get; set; }

        public bool IsHolderL { get; set; }
        public int Location { get; set; }
        /// <summary>
        /// //var v5 = (double)PlcHelper.Instance.ReadReal(6, 12);//刀柄半径
        /// </summary>
        public decimal HolderSD { get; set; }
        public bool IsHolderSD { get; set; }
        public string RfidCode { get; set; }

        /// <summary>
        /// 大直径理论
        /// </summary>
        public decimal Ace1DTheory { get; set; }
        /// <summary>
        /// 大长理论
        /// </summary>
        public decimal Ace1LTheory { get; set; }

    }

    public class Equ_TASKVMTest
    {
        /// <summary>
        /// 任务状态 1:未执行 2:执行中 3:已完成 4:异常
        /// </summary>
        public string Status { get; set; }

    }
    public class ApiResponse
    {
        public ApiResponse(string message, bool status = false)
        {
            this.Message = message;
            this.Status = status;
        }

        public ApiResponse(bool status, object result)
        {
            this.Status = status;
            this.Result = result;
        }

        public string Message { get; set; }

        public bool Status { get; set; }

        public object Result { get; set; }
    }
    public class QueryParameter
    {
        public int PageIndex { get; set; }
        public int PageSize { get; set; }
        public string Search { get; set; }
    }
    public class ToDoParameter : QueryParameter
    {
        public int? Status { get; set; }
    }
    public class V_EQU_TOOL_ORDERTDD : V_EQU_TOOL_ORDER
    {
        public List<EQU_TASK> EQU_TASKTDDS { get; set; }
    }

    public class EQU_TOOL_Dto
    {
        [Required]
        public string RfidCode { get; set; }
        /// <summary>
        ///实际对刀长度
        /// </summary>
        [Display(Name = "实际对刀长度")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? reality_pairing_length { get; set; }

        /// <summary>
        ///实际加长杆长度
        /// </summary>
        [Display(Name = "实际加长杆长度")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? reality_extensions_length { get; set; }

        /// <summary>
        ///实际刀尖圆角
        /// </summary>
        [Display(Name = "实际刀尖圆角")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? reality_R { get; set; }

        /// <summary>
        ///刀尖圆角
        /// </summary>
        [Display(Name = "刀尖圆角")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? R { get; set; }

        /// <summary>
        ///刀长
        /// </summary>
        [Display(Name = "刀长")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? knife_length { get; set; }

        /// <summary>
        ///实际刀长
        /// </summary>
        [Display(Name = "实际刀长")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? reality_knife_length { get; set; }

        /// <summary>
        ///刃长
        /// </summary>
        [Display(Name = "刃长")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? blade_length { get; set; }

        /// <summary>
        ///实际刃长
        /// </summary>
        [Display(Name = "实际刃长")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? reality_blade_length { get; set; }


        [Display(Name = "刀柄大直径")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? HolderBD { get; set; }

        /// <summary>
        ///刀柄大直径
        /// </summary>
        [Display(Name = "刀柄大直径")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? HolderSD { get; set; }

        /// <summary>
        ///刀柄长
        /// </summary>
        [Display(Name = "刀柄长")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? HolderL { get; set; }

        ///// <summary>
        /////加长杆1
        ///// </summary>
        //[Display(Name = "加长杆1")]
        //[MaxLength(50)]
        //[Column(TypeName = "nvarchar(50)")]
        //[Editable(true)]
        //public string Accessorie1Code { get; set; }

        ///// <summary>
        /////加长杆小直径
        ///// </summary>
        //[Display(Name = "加长杆小直径")]
        //[Column(TypeName = "decimal")]
        //[Editable(true)]
        //public decimal? Ace1C { get; set; }

        /// <summary>
        ///加长杆大直径
        /// </summary>
        [Display(Name = "加长杆大直径")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? Ace1D { get; set; }

        ///// <summary>
        /////加长杆小长
        ///// </summary>
        //[Display(Name = "加长杆小长")]
        //[Column(TypeName = "decimal")]
        //[Editable(true)]
        //public decimal? Ace1L1 { get; set; }

        /// <summary>
        ///加长杆大长
        /// </summary>
        [Display(Name = "加长杆大长")]
        [Column(TypeName = "decimal")]
        [Editable(true)]
        public decimal? Ace1L { get; set; }

        ///// <summary>
        /////加长杆2
        ///// </summary>
        //[Display(Name = "加长杆2")]
        //[MaxLength(50)]
        //[Column(TypeName = "nvarchar(50)")]
        //public string Accessorie2Code { get; set; }

        ///// <summary>
        /////小直径
        ///// </summary>
        //[Display(Name = "小直径")]
        //[Column(TypeName = "decimal")]
        //public decimal? Ace2C { get; set; }

        /// <summary>
        ///大直径
        /// </summary>
        [Display(Name = "大直径")]
        [Column(TypeName = "decimal")]
        public decimal? Ace2D { get; set; }

        ///// <summary>
        /////小长
        ///// </summary>
        //[Display(Name = "小长")]
        //[Column(TypeName = "decimal")]
        //public decimal? Ace2L1 { get; set; }

        /// <summary>
        ///大长
        /// </summary>
        [Display(Name = "大长")]
        [Column(TypeName = "decimal")]
        public decimal? Ace2L { get; set; }

        ///// <summary>
        /////加长杆3
        ///// </summary>
        //[Display(Name = "加长杆3")]
        //[MaxLength(50)]
        //[Column(TypeName = "nvarchar(50)")]
        //public string Accessorie3_Code { get; set; }

        ///// <summary>
        /////小直径
        ///// </summary>
        //[Display(Name = "小直径")]
        //[Column(TypeName = "decimal")]
        //public decimal? Ace3C { get; set; }

        /// <summary>
        ///大直径
        /// </summary>
        [Display(Name = "大直径")]
        [Column(TypeName = "decimal")]
        public decimal? Ace3D { get; set; }

        ///// <summary>
        /////小长
        ///// </summary>
        //[Display(Name = "小长")]
        //[Column(TypeName = "decimal")]
        //public decimal? Ace3L1 { get; set; }

        /// <summary>
        ///大长
        /// </summary>
        [Display(Name = "大长")]
        [Column(TypeName = "decimal")]
        public decimal? Ace3L { get; set; }
        /// <summary>
        /// 判定结果
        /// </summary>

        public int CheckResult { get; set; }
    }
    public class INTE_SHELVES_Dto
    {
        public string Identifier { get; set; }
    }
    /// <summary>
    /// 待办事项数据实体
    /// </summary>
    public class ToDoDto : EQU_TOOL
    {
        public List<EQU_COM_DEFINITION_TASK> TaskItems { get; set; }
        public string EquipmentNameZH { get; set; }
        public string Command { get; set; }
        public string SubPathNo { get; set; }
        public string ExecuteStart { get; set; }
        public string EquipmentCode { get; set; }
        public string OrderCode { get; set; }
        private string title;
        private string content;
        private int status;

        public string Title
        {
            get { return title; }
            set { title = value; }
        }

        public string Content
        {
            get { return content; }
            set { content = value; }
        }

        public int Status
        {
            get { return status; }
            set { status = value; }
        }
        public DateTime CreateDate { get; set; }
        public DateTime UpdateDate { get; set; }
    }
    public class BaseDto : INotifyPropertyChanged
    {
        public int Id { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 实现通知更新
        /// </summary>
        /// <param name="propertyName"></param>
        public void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    /// <summary>
    /// 汇总
    /// </summary>
    public class SummaryDto : BaseDto
    {
        private int sum;
        private int completedCount;
        private int memoeCount;
        private string completedRatio;


        /// <summary>
        /// 待办事项总数
        /// </summary>
        public int Sum
        {
            get { return sum; }
            set { sum = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// 完成待办事项数量
        /// </summary>
        public int CompletedCount
        {
            get { return completedCount; }
            set { completedCount = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// 备忘录数量
        /// </summary>
        public int MemoeCount
        {
            get { return memoeCount; }
            set { memoeCount = value; OnPropertyChanged(); }
        }

        /// <summary>
        /// 完成比例
        /// </summary>
        public string CompletedRatio
        {
            get { return completedRatio; }
            set { completedRatio = value; OnPropertyChanged(); }
        }

        private ObservableCollection<ToDoDto> todoList;
        //private ObservableCollection<MemoDto> memoList;

        /// <summary>
        /// 待办事项列表
        /// </summary>
        public ObservableCollection<ToDoDto> ToDoList
        {
            get { return todoList; }
            set { todoList = value; OnPropertyChanged(); }
        }

        ///// <summary>
        ///// 备忘录列表
        ///// </summary>
        //public ObservableCollection<MemoDto> MemoList
        //{
        //    get { return memoList; }
        //    set { memoList = value; OnPropertyChanged(); }
        //}
    }

    /// <summary>
    /// Represents the default implementation of the <see cref="IPagedList{T}"/> interface.
    /// </summary>
    /// <typeparam name="T">The type of the data to page 页类型的数据</typeparam>
    public class PagedList<T> : IPagedList<T>
    {
        /// <summary>
        /// Gets or sets the index of the page.
        /// 获得页的起始页
        /// </summary>
        /// <value>The index of the page.</value>
        public int PageIndex { get; set; }
        /// <summary>
        /// Gets or sets the size of the page.
        /// 获得页大小
        /// </summary>
        /// <value>The size of the page.</value>
        public int PageSize { get; set; }
        /// <summary>
        /// Gets or sets the total count.
        /// 获得总数
        /// </summary>
        /// <value>The total count.</value>
        public int TotalCount { get; set; }
        /// <summary>
        /// Gets or sets the total pages.
        /// 获得总页数
        /// </summary>
        /// <value>The total pages.</value>
        public int TotalPages { get; set; }
        /// <summary>
        /// Gets or sets the index from.
        /// 从索引起
        /// </summary>
        /// <value>The index from.</value>
        public int IndexFrom { get; set; }

        /// <summary>
        /// Gets or sets the items.
        /// 数据
        /// </summary>
        /// <value>The items.</value>
        public IList<T> Items { get; set; }

        /// <summary>
        /// Gets the has previous page.
        /// 获取前一页
        /// </summary>
        /// <value>The has previous page.</value>
        public bool HasPreviousPage => PageIndex - IndexFrom > 0;

        /// <summary>
        /// Gets the has next page.
        /// 获取下一页
        /// </summary>
        /// <value>The has next page.</value>
        public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages;

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{T}" /> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="pageIndex">The index of the page.</param>
        /// <param name="pageSize">The size of the page.</param>
        /// <param name="indexFrom">The index from.</param>
        public PagedList(IEnumerable<T> source, int pageIndex, int pageSize, int indexFrom)
        {
            if (indexFrom > pageIndex)
            {
                throw new ArgumentException($"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
            }

            if (source is IQueryable<T> querable)
            {
                PageIndex = pageIndex;
                PageSize = pageSize;
                IndexFrom = indexFrom;
                TotalCount = querable.Count();
                TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);

                Items = querable.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToList();
            }
            else
            {
                PageIndex = pageIndex;
                PageSize = pageSize;
                IndexFrom = indexFrom;
                TotalCount = source.Count();
                TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);

                Items = source.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToList();
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{T}" /> class.
        /// </summary>
        public PagedList() => Items = new T[0];
    }


    /// <summary>
    /// Provides the implementation of the <see cref="IPagedList{T}"/> and converter.
    /// </summary>
    /// <typeparam name="TSource">The type of the source.</typeparam>
    /// <typeparam name="TResult">The type of the result.</typeparam>
    public class PagedList<TSource, TResult> : IPagedList<TResult>
    {
        /// <summary>
        /// Gets the index of the page.
        /// </summary>
        /// <value>The index of the page.</value>
        public int PageIndex { get; }
        /// <summary>
        /// Gets the size of the page.
        /// </summary>
        /// <value>The size of the page.</value>
        public int PageSize { get; }
        /// <summary>
        /// Gets the total count.
        /// </summary>
        /// <value>The total count.</value>
        public int TotalCount { get; }
        /// <summary>
        /// Gets the total pages.
        /// </summary>
        /// <value>The total pages.</value>
        public int TotalPages { get; }
        /// <summary>
        /// Gets the index from.
        /// </summary>
        /// <value>The index from.</value>
        public int IndexFrom { get; }

        /// <summary>
        /// Gets the items.
        /// </summary>
        /// <value>The items.</value>
        public IList<TResult> Items { get; }

        /// <summary>
        /// Gets the has previous page.
        /// </summary>
        /// <value>The has previous page.</value>
        public bool HasPreviousPage => PageIndex - IndexFrom > 0;

        /// <summary>
        /// Gets the has next page.
        /// </summary>
        /// <value>The has next page.</value>
        public bool HasNextPage => PageIndex - IndexFrom + 1 < TotalPages;

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{TSource, TResult}" /> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="converter">The converter.</param>
        /// <param name="pageIndex">The index of the page.</param>
        /// <param name="pageSize">The size of the page.</param>
        /// <param name="indexFrom">The index from.</param>
        public PagedList(IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> converter, int pageIndex, int pageSize, int indexFrom)
        {
            if (indexFrom > pageIndex)
            {
                throw new ArgumentException($"indexFrom: {indexFrom} > pageIndex: {pageIndex}, must indexFrom <= pageIndex");
            }

            if (source is IQueryable<TSource> querable)
            {
                PageIndex = pageIndex;
                PageSize = pageSize;
                IndexFrom = indexFrom;
                TotalCount = querable.Count();
                TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);

                var items = querable.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToArray();

                Items = new List<TResult>(converter(items));
            }
            else
            {
                PageIndex = pageIndex;
                PageSize = pageSize;
                IndexFrom = indexFrom;
                TotalCount = source.Count();
                TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);

                var items = source.Skip((PageIndex - IndexFrom) * PageSize).Take(PageSize).ToArray();

                Items = new List<TResult>(converter(items));
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PagedList{TSource, TResult}" /> class.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="converter">The converter.</param>
        public PagedList(IPagedList<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> converter)
        {
            PageIndex = source.PageIndex;
            PageSize = source.PageSize;
            IndexFrom = source.IndexFrom;
            TotalCount = source.TotalCount;
            TotalPages = source.TotalPages;

            Items = new List<TResult>(converter(source.Items));
        }
    }

    /// <summary>
    /// Provides some help methods for <see cref="IPagedList{T}"/> interface.
    /// </summary>
    public static class PagedList
    {
        /// <summary>
        /// Creates an empty of <see cref="IPagedList{T}"/>.
        /// </summary>
        /// <typeparam name="T">The type for paging </typeparam>
        /// <returns>An empty instance of <see cref="IPagedList{T}"/>.</returns>
        public static IPagedList<T> Empty<T>() => new PagedList<T>();
        /// <summary>
        /// Creates a new instance of <see cref="IPagedList{TResult}"/> from source of <see cref="IPagedList{TSource}"/> instance.
        /// </summary>
        /// <typeparam name="TResult">The type of the result.</typeparam>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <param name="source">The source.</param>
        /// <param name="converter">The converter.</param>
        /// <returns>An instance of <see cref="IPagedList{TResult}"/>.</returns>
        public static IPagedList<TResult> From<TResult, TSource>(IPagedList<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> converter) => new PagedList<TSource, TResult>(source, converter);
    }

    /// <summary>
    /// Provides the interface(s) for paged list of any type.
    /// 为任何类型的分页列表提供接口
    /// </summary>
    /// <typeparam name="T">The type for paging.分页的类型</typeparam>
    public interface IPagedList<T>
    {
        /// <summary>
        /// Gets the index start value.
        /// 获取索引起始值
        /// </summary>
        /// <value>The index start value.</value>
        int IndexFrom { get; }
        /// <summary>
        /// Gets the page index (current).
        /// 获取页索引(当前)
        /// </summary>
        int PageIndex { get; }
        /// <summary>
        /// Gets the page size.
        /// 获取页面大小
        /// </summary>
        int PageSize { get; }
        /// <summary>
        /// Gets the total count of the list of type <typeparamref name="T"/>
        /// 获取类型列表的总计数
        /// </summary>
        int TotalCount { get; }
        /// <summary>
        /// Gets the total pages.
        /// 获取页面总数
        /// </summary>
        int TotalPages { get; }
        /// <summary>
        /// Gets the current page items.
        /// 获取当前页项
        /// </summary>
        IList<T> Items { get; }
        /// <summary>
        /// Gets the has previous page.
        /// 获取前一页
        /// </summary>
        /// <value>The has previous page.</value>
        bool HasPreviousPage { get; }

        /// <summary>
        /// Gets the has next page.
        /// 获取下一页
        /// </summary>
        /// <value>The has next page.</value>
        bool HasNextPage { get; }
    }

    #region excel

    #region 主要实体
    //实体主要部分，根据xml生成
    [Serializable]
    public class wsDr
    {
        [XmlElement(ElementName = "twoCellAnchor")]//指定节点名称
        public List<twoCellAnchor> twoCellAnchorList { get; set; }

    }
    //读取图片实体
    public class Relationships
    {
        [XmlElement("Relationship")]
        public List<Relationship> Relationship { get; set; }

    }
    #endregion
    #region 其他实体
    public class from
    {
        //这里列名称和节点名称相同，不需要特意指定xml节点名称
        public int col { get; set; }
        public int row { get; set; }

    }
    public class to
    {
        public int col { get; set; }
        public int row { get; set; }
    }
    public class cNvPr
    {
        [XmlAttribute("id")]
        public string _id { get; set; }
        [XmlAttribute("name")]
        public string _name { get; set; }
        // public Image img { get; set; }
        public string imgUrl { get; set; }
    }
    public class blip
    {
        /*手动指定xml命名空间，该命名空间使用..Where(x => x.IsNamespaceDeclaration).Remove()移除不了。
         * 注：xml中这块读取出来后不认为它是命名空间,因为是子级特意指定的
         */
        [XmlAttribute("embed", Namespace = "http://schemas.openxmlformats.org/officeDocument/2006/relationships")]
        public string imgid { get; set; }

    }
    public class blipFill
    {
        [XmlElement("blip")]
        public blip blip1 { get; set; }

    }
    public class nvPicPr
    {
        [XmlElement(ElementName = "cNvPr")]
        public cNvPr cNvPr1 { get; set; }

    }
    public class pic
    {
        [XmlElement(ElementName = "nvPicPr")]
        public nvPicPr nvPicPr1 { get; set; }
        [XmlElement("blipFill")]
        public blipFill blipFill1 { get; set; }
    }
    public class twoCellAnchor
    {
        [XmlElement(ElementName = "from")]
        public from from1 { get; set; }
        [XmlElement(ElementName = "to")]
        public to to1 { get; set; }
        [XmlElement(ElementName = "pic")]
        public pic pic1 { get; set; }

    }

    public class Relationship
    {
        [XmlAttribute("Id")]
        public string Id { get; set; }
        [XmlAttribute("Target")]
        public string Target { get; set; }
        //public Image img { get; set; }
        public string imgUrl { get; set; }
    }
    #endregion

    #endregion

    #region flow

    public class Flow
    {
        public List<nodes> nodes { get; set; }
        public List<edges> edges { get; set; }
    }
    public class nodes
    {
        public string id { get; set; }
        public string type { get; set; }
        public int x { get; set; }
        public int y { get; set; }
        public string text { get; set; }
    }
    public class edges
    {
        public string type { get; set; }
        public string sourceNodeId { get; set; }
        public string targetNodeId { get; set; }
    }
    #endregion
}
